home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
gnu
/
nethack.lha
/
nethack-3.1
/
util
/
recover.c
< prev
Wrap
C/C++ Source or Header
|
1993-01-21
|
6KB
|
278 lines
/* recover.c - NetHack version 3.1 */
/*
* Utility for reconstructing NetHack save file from a set of individual
* level files. Requires that the `checkpoint' option be enabled at the
* time NetHack creates those level files.
*/
#include "config.h"
#if !defined(O_WRONLY) && !defined(LSC) && !defined(AZTEC_C)
#include <fcntl.h>
#endif
#ifndef VMS
# ifdef exit
# undef exit
# endif
#ifdef MICRO
extern void FDECL(exit, (int));
#endif
#else /* VMS */
extern int FDECL(vms_creat, (const char *,unsigned));
extern int FDECL(vms_open, (const char *,int,unsigned));
#endif /* VMS */
int FDECL(restore_savefile, (char *));
void FDECL(set_levelfile_name, (int));
int FDECL(open_levelfile, (int));
int FDECL(create_savefile, (char *));
void FDECL(copy_bytes, (int,int));
#ifdef UNIX
#define SAVESIZE (PL_NSIZ + 13) /* save/99999player.e */
#else
# ifdef VMS
#define SAVESIZE (PL_NSIZ + 22) /* [.save]<uid>player.e;1 */
# else
#define SAVESIZE FILENAME /* from macconf.h or pcconf.h */
# endif
#endif
char savename[SAVESIZE]; /* holds relative path of save file from playground */
int
main(argc, argv)
int argc;
char *argv[];
{
int argno;
char *dir = (char *)0;
if (argc == 1 || (argc == 2 && !strcmp(argv[1], "-"))) {
(void) fprintf(stderr,
"Usage: %s [-d directory] base1 base2 ...\n",
argv[0]);
exit(1);
}
argno = 1;
if (!strncmp(argv[argno], "-d", 2)) {
dir = argv[argno]+2;
if (*dir == '=' || *dir == ':') dir++;
if (!*dir && argc > argno) {
argno++;
dir = argv[argno];
}
if (!*dir) {
(void) fprintf(stderr,
"%s: flag -d must be followed by a directory name.\n",
argv[0]);
exit(1);
}
argno++;
}
if (!dir) dir = getenv("NETHACKDIR");
if (!dir) dir = getenv("HACKDIR");
#if defined(SECURE) && !defined(VMS)
if (dir
# ifdef HACKDIR
&& strcmp(dir, HACKDIR)
# endif
) {
(void) setgid(getgid());
(void) setuid(getuid());
}
#endif /* SECURE && !VMS */
#ifdef HACKDIR
if (!dir) dir = HACKDIR;
#endif
if (dir && chdir(dir) < 0) {
(void) fprintf(stderr, "%s: cannot chdir to %s.\n",
argv[0], dir);
exit(1);
}
while (argc > argno) {
(void) restore_savefile(argv[argno]);
argno++;
}
#ifndef VMS
return 0;
#else
return 1; /* vms success */
#endif /*VMS*/
}
static char lock[256];
void
set_levelfile_name(lev)
int lev;
{
char *tf;
tf = rindex(lock, '.');
if (!tf) {
tf = lock;
while (*tf) tf++;
}
#ifdef VMS
(void) sprintf(tf, ".%d;1", lev);
#else
(void) sprintf(tf, ".%d", lev);
#endif
}
int
open_levelfile(lev)
int lev;
{
int fd;
set_levelfile_name(lev);
#ifdef MICRO
fd = open(lock, O_RDONLY | O_BINARY);
#else
fd = open(lock, O_RDONLY, 0);
#endif
return fd;
}
int
create_savefile(savename)
char *savename;
{
int fd;
#ifdef MICRO
fd = open(savename, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FCMASK);
#else
fd = creat(savename, FCMASK);
#endif
return fd;
}
void
copy_bytes(ifd, ofd)
int ifd, ofd;
{
char buf[BUFSIZ];
int nfrom, nto;
do {
nfrom = read(ifd, buf, BUFSIZ);
nto = write(ofd, buf, nfrom);
if (nto != nfrom) {
(void) fprintf(stderr, "file copy failed!\n");
exit(1);
}
} while (nfrom == BUFSIZ);
}
int
restore_savefile(basename)
char *basename;
{
int gfd, lfd, sfd;
int lev, savelev, hpid;
xchar levc;
/* level 0 file contains:
* pid of creating process (ignored here)
* level number for current level of save file
* name of save file nethack would have created
* and game state
*/
(void) strcpy(lock, basename);
gfd = open_levelfile(0);
if (gfd < 0) {
(void) fprintf(stderr, "Cannot open level 0 for %s.\n", basename);
return(-1);
}
(void) read(gfd, (genericptr_t) &hpid, sizeof(hpid));
if (read(gfd, (genericptr_t) &savelev, sizeof(savelev))
!= sizeof(savelev)) {
(void) fprintf(stderr,
"Checkpointing was not in effect for %s -- recovery impossible.\n",
basename);
(void) close(gfd);
return(-1);
}
(void) read(gfd, (genericptr_t) savename, sizeof(savename));
/* save file should contain:
* current level (including pets)
* (non-level-based) game state
* other levels
*/
sfd = create_savefile(savename);
if (sfd < 0) {
(void) fprintf(stderr, "Cannot create savefile %s.\n", savename);
(void) close(gfd);
return(-1);
}
lfd = open_levelfile(savelev);
if (lfd < 0) {
(void) fprintf(stderr, "Cannot open level of save for %s.\n",
basename);
(void) close(gfd);
(void) close(sfd);
return(-1);
}
copy_bytes(lfd, sfd);
(void) close(lfd);
(void) unlink(lock);
copy_bytes(gfd, sfd);
(void) close(gfd);
set_levelfile_name(0);
(void) unlink(lock);
for (lev = 1; lev < 256; lev++) {
/* level numbers are kept in xchars in save.c, so the
* maximum level number (for the endlevel) must be < 256
*/
if (lev != savelev) {
lfd = open_levelfile(lev);
if (lfd >= 0) {
/* any or all of these may not exist */
levc = (xchar) lev;
write(sfd, (genericptr_t) &levc, sizeof(levc));
copy_bytes(lfd, sfd);
(void) close(lfd);
(void) unlink(lock);
}
}
}
(void) close(sfd);
#ifdef AMIGA
/* we need to create an icon for the saved game
* or HackWB won't notice the file.
*/
{
char iconfile[FILENAME];
int in, out;
sprintf(iconfile,"%s.info",savename);
in=open("NetHack:default.icon",O_RDONLY);
out=open(iconfile,O_WRONLY | O_TRUNC | O_CREAT);
if(in > -1 && out > -1){
copy_bytes(in,out);
}
if(in > -1)close(in);
if(out > -1)close(out);
}
#endif
return(0);
}
/*recover.c*/